/**
 * 项目名：	Rumba Plan
 * 
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2006，所有权利保留。
 * 
 * 文件名：	SCE.java
 * 模块说明：	
 * 修改历史：
 * 2006-7-24 - lxm - 创建。
 */
package com.hd123.rumba.sql;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import com.hd123.rumba.exception.BusinessException;

/**
 * 条件表达式(SQL Condition Expression)对象
 * <p>
 * 
 * 设计目的在于为程序开发者提供一个关于HQL语言条件表达式的对象表达。通过这个对象可以理论上可以表达任意复杂度的条件表达<br>
 * 式，可以将此用于SQLSubquery中的where和having子句的构造。
 * 
 * @author lxm
 * 
 */
public class SCE {

  private static final long serialVersionUID = 300100L;

  /**
   * 构造一个条件表达式。
   * 
   * @param condition
   *          条件字符串，符合HQL语法。
   * @param parameterValue
   *          条件参数。可选参数。
   * @param wildcard
   *          通配符，取值参见常量“SQLSubquery.WC_*”。可选参数，默认为SQLSubquery.WC_NONE。
   * @param toUpperCase
   *          是否将参数转换为大写。可选参数，默认为false。
   * @param hasParameter
   *          是否有参数。
   * @return 返回条件表达式对象。可选参数。
   */
  public static SCE cond(String condition) throws BusinessException {
    return cond(condition, null, WC_NONE, false, false);
  }

  public static SCE cond(String condition, Object parameterValue) throws BusinessException {
    return cond(condition, parameterValue, WC_NONE, false, true);
  }

  public static SCE cond(String condition, Object parameterValue, int wildcard)
      throws BusinessException {
    return cond(condition, parameterValue, wildcard, false, true);
  }

  public static SCE cond(String condition, Object parameterValue, int wildcard, boolean toUpperCase)
      throws BusinessException {
    return cond(condition, parameterValue, wildcard, toUpperCase, true);
  }

  public static SCE cond(String condition, Object parameterValue, int wildcard,
      boolean toUpperCase, boolean hasParameter) throws BusinessException {
    if (condition == null)
      throw new BusinessException("传入的参数condition不可为空。");
    if (toUpperCase && parameterValue != null && parameterValue instanceof String)
      parameterValue = ((String) parameterValue).toUpperCase();
    SCE sce = new SCE();
    sce.operator = VALUE_OPERATOR_COND;
    sce.condition = condition;
    sce.hasParameter = hasParameter;
    sce.parameters.clear();
    sce.parameters.add(parameterValue);
    sce.wildcard = wildcard;
    return sce;
  }

  /**
   * not运算
   * 
   * @param sce
   * @return
   */
  public static SCE not(SCE sce) throws BusinessException {
    return build(VALUE_OPERATOR_NOT, sce);
  }

  /**
   * and运算
   * 
   * @param sce1
   * @param sce2
   * @return
   */
  public static SCE and(SCE sce1, SCE sce2) throws BusinessException {
    return build(VALUE_OPERATOR_AND, sce1, sce2);
  }

  /**
   * and运算
   * 
   * @param sces
   * @return
   */
  public static SCE and(SCE[] sces) throws BusinessException {
    return build(VALUE_OPERATOR_AND, sces);
  }

  /**
   * or运算
   * 
   * @param sce1
   * @param sce2
   * @return
   */
  public static SCE or(SCE sce1, SCE sce2) throws BusinessException {
    return build(VALUE_OPERATOR_OR, sce1, sce2);
  }

  /**
   * or运算
   * 
   * @param sces
   * @return
   */
  public static SCE or(SCE[] sces) throws BusinessException {
    return build(VALUE_OPERATOR_OR, sces);
  }

  /** 运算符取值：单一条件 */
  public static final Integer VALUE_OPERATOR_COND = new Integer(0);
  /** 运算符取值：not运算 */
  public static final Integer VALUE_OPERATOR_NOT = new Integer(1);
  /** 运算符取值：and运算 */
  public static final Integer VALUE_OPERATOR_AND = new Integer(2);
  /** 运算符取值：or运算 */
  public static final Integer VALUE_OPERATOR_OR = new Integer(3);
  /** 通配符：无通配符 */
  public static final int WC_NONE = SQLSubquery.WC_NONE;
  /** 通配符：通配符位于最左边 */
  public static final int WC_LEFT = SQLSubquery.WC_LEFT;
  /** 通配符：通配符位于最右边 */
  public static final int WC_RIGHT = SQLSubquery.WC_RIGHT;
  /** 通配符：通配符位于两边 */
  public static final int WC_BOTH = SQLSubquery.WC_BOTH;

  /** 运算符 */
  private Integer operator;
  /** 条件字符串。只有当operator=VALUE_OPERATOR_COND时有效。 */
  private String condition = null;
  /** 是否有参数。 */
  private boolean hasParameter = false;
  /** 通配符 */
  private int wildcard = WC_NONE;
  /** 参数列表 */
  private List parameters = new ArrayList();

  /**
   * 构造函数。
   * <p>
   * 设置默认运算符为VALUE_OPERATOR_COND。
   */
  public SCE() {
    super();
    this.operator = VALUE_OPERATOR_COND;
  }

  /**
   * 构造函数。
   * 
   * @param operator
   *          指定运算符。取值参见以“SCE.VALUE_OPERATOR_”开头的常量。
   */
  public SCE(Integer operator) {
    super();
    this.operator = operator;
  }

  /**
   * 保持现有运算不变，添加一个条件表达式。
   * 
   * @param sce
   *          被添加的条件表达式。
   */
  public void append(SCE sce) {
    if (sce.getParameters().size() > 0)
      this.parameters.add(sce);
  }

  /**
   * 取得参数列表。
   * 
   * @return
   */
  public Vector getParametersVector() throws BusinessException {
    Vector v = new Vector();
    if (VALUE_OPERATOR_COND.equals(operator)) {
      if (hasParameter && parameters.size() >= 1)
        addSingleObjectToVector(v, parameters.get(0), wildcard);
    } else if (VALUE_OPERATOR_NOT.equals(operator)) {
      if (parameters.size() < 1)
        throw new BusinessException(this.getClass().getName() + ": 缺少必要的参数。");
      SCE sce = (SCE) parameters.get(0);
      v.addAll(sce.getParametersVector());
    } else {
      for (int i = 0; i < parameters.size(); i++) {
        SCE sce = (SCE) parameters.get(i);
        v.addAll(sce.getParametersVector());
      }
    }
    return v;
  }

  /**
   * 转换为字符串。可被用于HQL。
   * 
   * @return
   */
  public String toSQL() throws BusinessException {
    if (VALUE_OPERATOR_COND.equals(operator))
      return toSQL_cond();
    else if (VALUE_OPERATOR_NOT.equals(operator))
      return toSQL_1("not");
    else if (VALUE_OPERATOR_AND.equals(operator))
      return toSQL_s("and");
    else
      // if (VALUE_OPERATOR_OR.equals(operator))
      return toSQL_s("or");
  }

  public String getCondition() {
    return condition;
  }

  public void setCondition(String condition) {
    this.condition = condition;
  }

  public Integer getOperator() {
    return operator;
  }

  public void setOperator(Integer operator) {
    this.operator = operator;
  }

  public List getParameters() {
    return parameters;
  }

  public void setParameters(List parameters) {
    this.parameters = parameters;
  }

  public boolean isHasParameter() {
    return hasParameter;
  }

  public void setHasParameter(boolean hasParameter) {
    this.hasParameter = hasParameter;
  }

  public int getWildcard() {
    return wildcard;
  }

  public void setWildcard(int wildcard) {
    this.wildcard = wildcard;
  }

  private static SCE build(Integer operator, SCE sce) throws BusinessException {
    if (sce == null)
      throw new BusinessException("传入的参数sce不可为空。");
    SCE result = new SCE();
    result.operator = operator;
    result.parameters.clear();
    result.parameters.add(sce);
    return result;
  }

  private static SCE build(Integer operator, SCE sce1, SCE sce2) throws BusinessException {
    if (sce1 == null)
      throw new BusinessException("传入的参数sce1不可为空。");
    if (sce2 == null)
      throw new BusinessException("传入的参数sce2不可为空。");
    SCE result = new SCE();
    result.operator = operator;
    result.parameters.clear();
    result.parameters.add(sce1);
    result.parameters.add(sce2);
    return result;
  }

  private static SCE build(Integer operator, SCE[] sces) throws BusinessException {
    if (sces == null)
      throw new BusinessException("传入的参数sces不可为空。");
    for (int i = 0; i < sces.length; i++)
      if (sces[i] == null)
        throw new BusinessException("传入的参数sces[" + i + "]不可为空。");
    SCE result = new SCE();
    result.operator = operator;
    result.parameters.clear();
    for (int i = 0; i < sces.length; i++)
      result.parameters.add(sces[i]);
    return result;
  }

  private String toSQL_cond() throws BusinessException {
    String s = condition.toLowerCase();
    if (hasParameter && s.indexOf(" in ") >= 0) {
      String ss = "";
      if (parameters.get(0) instanceof Object[]) {
        Object[] params = (Object[]) parameters.get(0);
        for (int i = 0; i < params.length; i++) {
          if (!"".equals(ss))
            ss += ",";
          ss += "?";
        }
      } else
        ss = "?";
      ss = "(" + ss + ")";
      return condition.replaceAll("\\?", ss);
    } else
      return condition;
  }

  private String toSQL_1(String operStr) throws BusinessException {
    if (parameters.size() < 1)
      throw new BusinessException(this.getClass().getName() + ": 缺少必要的参数。");
    if (!(parameters.get(0) instanceof SCE))
      throw new BusinessException(this.getClass().getName() + ": 缺少必要的参数。");
    SCE sce = (SCE) parameters.get(0);
    return operStr + " (" + sce.toSQL() + ")";
  }

  private String toSQL_s(String operStr) throws BusinessException {
    StringBuffer sb = new StringBuffer();
    if (parameters.size() == 1)
      sb.append(((SCE) parameters.get(0)).toSQL());
    else
      for (int i = 0; i < parameters.size(); i++) {
        String s = "";
        if (sb.length() > 0)
          s = " " + operStr + " ";
        SCE sce = (SCE) parameters.get(i);
        s += "(" + sce.toSQL() + ")";
        sb.append(s);
      }
    return sb.toString();
  }

  private void addSingleObjectToVector(Vector v, Object param, int wildcard) {
    if (param instanceof String) {
      if (wildcard == WC_NONE)
        v.add(param);
      else if (wildcard == WC_LEFT)
        v.add("%" + param);
      else if (wildcard == WC_RIGHT)
        v.add(param + "%");
      else if (wildcard == WC_BOTH)
        v.add("%" + param + "%");
    } else if (param instanceof java.util.Date) {
      // be sure to convert a java.util.Date to a java.sql.Timestamp!
      java.util.Date d = (java.util.Date) param;
      v.add(new java.sql.Timestamp(d.getTime()));
    } else if (param instanceof Object[]) {
      Object[] paramArray = (Object[]) param;
      for (int i = 0; i < paramArray.length; i++)
        v.add(paramArray[i]);
    } else {
      v.add(param);
    }
  }

}
